/**
 * Copyright (c) 2010 Pablo Muñoz Galindo
 * <p>
 * Este software está licenciado bajo los términos de la licencia GNU GPLv3
 * <br>
 * Para más información:
 * <a href="http://www.gnu.org/licenses/gpl-3.0-standalone.html"> http://www.gnu.org/licenses/gpl-3.0-standalone.html </a>
 * <br>
 * Este software es distribuido "como es", no ofreciendo garantías de ningún tipo. La responsabilidad
 * de su uso queda bajo la cuenta y riesgo del propio usuario.
 *
 */
package esteganografo.core;

import java.io.FileInputStream;
import java.io.InputStream;

/**
 * Clase para decodificar texto en claro guardado dentro de un fichero
 *
 * @author Pablo Muñoz Galindo
 * @version 0.1b
 */
public class Decoder {
    
    /**
     * Fichero portador de la información
     */
    public String fichero_orig;

    /**
     * Constructor a partir del nombre del fichero portador de la información
     * @param fichero_orig Ruta al fichero portador
     */
    public Decoder(String fichero_orig) {
        this.fichero_orig = fichero_orig;
    }

    /**
     * Método que decodifica el contenido del fichero portador y devuelve un String
     * con el mismo
     *
     * @return String mensaje contenido en el fichero
     * @throws Exception si hay errores de entrada/salida
     */
    public String decode() throws Exception {
        InputStream in = new FileInputStream(fichero_orig);
        String mensaje = "";
        long n = 0;

        //Se lee y almacena la cabecera del fichero. Aquí podríamos comprobar si es BMP, WAV, etc
        byte[] header = new byte[53];
        in.read(header);

        //Se lee el tamaño del mensaje a decodificar
        byte[] marker = new byte[64];
        in.read(marker);
        n = getTamanoMensaje(marker);

        //Se comienzan a leer los caracteres del mensaje
        byte[] caracter = new byte[8];
        for (int i = 0; i < n; i++) {
            if (in.read(caracter) < 0) {
                throw new Exception("Ya no hay más bytes!!!!");
            }
            mensaje += getChar(caracter);
        }

        return mensaje;
    }

    /*
     * Método privado que interpreta la marca de número de bytes codificados
     * contenida en el fichero portador y devuelve un long con dicha información
     */
    private long getTamanoMensaje(byte[] marker)
            throws Exception {
        if (marker.length != 64) {
            throw new Exception("Número de bytes insuficiente");
        }
        String longitud_mensaje = "";
        for (byte b : marker) {
            longitud_mensaje += Byte.toString((byte) (b & 0x01));
        }
        return Long.parseLong(longitud_mensaje, 2);
    }

    /*
     *Método privado para  componer un caracter a partir de los LSB de 8 bytes
     */
    private char getChar(byte[] bytes)
            throws Exception {
        String binaryCharCode = "";
        String bit = "";
        if (bytes.length != 8) {
            throw new Exception("Número de bytes insuficiente");
        }
        for (int i = 0; i < bytes.length; i++) {
            bit = Long.toBinaryString((byte) (bytes[i] & 0x01));
            binaryCharCode += bit;
        }
        char c = (char) Integer.parseInt(binaryCharCode, 2);
        return c;
    }
}
